/*****************************************************************************
 *   Copyright(C)2009-2024 by VSF Team                                       *
 *                                                                           *
 *  Licensed under the Apache License, Version 2.0 (the "License");          *
 *  you may not use this file except in compliance with the License.         *
 *  You may obtain a copy of the License at                                  *
 *                                                                           *
 *     http://www.apache.org/licenses/LICENSE-2.0                            *
 *                                                                           *
 *  Unless required by applicable law or agreed to in writing, software      *
 *  distributed under the License is distributed on an "AS IS" BASIS,        *
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
 *  See the License for the specific language governing permissions and      *
 *  limitations under the License.                                           *
 *                                                                           *
 ****************************************************************************/

/*============================ INCLUDES ======================================*/

#include "component/test/vsf_test/vsf_test.h"
#include "hme_wdt.h"
#include "vsf_hal.h"

/*============================ MACROS ========================================*/

#define VSF_TEST_DEMO_USARTS {&vsf_hw_usart0, &vsf_hw_usart1}
#define VSF_TEST_DEMO_USART  vsf_hw_usart0

/*============================ TYPES =========================================*/
/*============================ INCLUDES ======================================*/
/*============================ PROTOTYPES ====================================*/

static void __hme_wdt_init(vsf_test_wdt_t *wdt, uint32_t timeout_ms);
static void __hme_wdt_feed(vsf_test_wdt_t *wdt);

/*============================ LOCAL VARIABLES ===============================*/

static vsf_test_t __test = {
    .wdt =
        {
            .internal =
                {
                    .init = __hme_wdt_init, // vsf_test_hal_wdt_init,
                    .feed = __hme_wdt_feed, // vsf_test_hal_wdt_feed,
                },
            .external =
                {
                    .init = vsf_test_stdio_wdt_init,
                    .feed = vsf_test_stdio_wdt_feed,
                },
        },
    .reboot =
        {
            .internal = vsf_arch_reset,
            .external = vsf_test_stdio_reboot,
        },
    .data = {
        .init = vsf_test_stdio_data_init,
        .sync = vsf_test_stdio_data_sync,
    }};
vsf_test_t *test = &__test;

/*============================ GLOBAL VARIABLES ==============================*/
/*============================ IMPLEMENTATION ================================*/

void NMI_Handler(void)
{
    vsf_test_reboot(test, VSF_TEST_RESULT_FAULT_HANDLER_FAIL, __FILE__,
                    __LINE__, __FUNCTION__, NULL);
}

void HardFault_Handler(void)
{
    vsf_test_reboot(test, VSF_TEST_RESULT_FAULT_HANDLER_FAIL, __FILE__,
                    __LINE__, __FUNCTION__, NULL);
}

void SVC_Handler(void)
{
    vsf_test_reboot(test, VSF_TEST_RESULT_FAULT_HANDLER_FAIL, __FILE__,
                    __LINE__, __FUNCTION__, NULL);
}

void WDT_Handler(void)
{
    HME_WDT_ClearITPendingBit();
    NVIC_DisableIRQ(WDT_IRQn);
}

static void __hme_wdt_init(vsf_test_wdt_t *wdt, uint32_t timeout_ms)
{
    HME_WDT_InitTypeDef Init;

    NVIC_EnableIRQ(WDT_IRQn);

    HME_WDT_StructInit(&Init);
    Init.InterruptFirst    = true;
    Init.InitTimeoutPeriod = WDT_TIMEOUT_PERIOD_16_POWER_OF_2;
    Init.TimeoutPeriod     = WDT_TIMEOUT_PERIOD_27_POWER_OF_2;
    HME_WDT_Init(&Init);
}

static void __hme_wdt_feed(vsf_test_wdt_t *wdt)
{
    HME_WDT_Restart();
}

static void __test_pass(void)
{
    int a = 100;
    int b = 50 + 50;

    VSF_TEST_ASSERT(test, a == b);
}

static void __test_fail(void)
{
    int a = 100;
    int b = 50 + 50;

    VSF_TEST_ASSERT(test, a != b);
}

static void __test_wdt(void)
{
    while (1);
}

void __test_unalign(void)
{
#ifdef __CORTEX_M
    SCB->CCR |= (1 << 3);
    volatile uint32_t *p     = (volatile uint32_t *)0x03;
    uint32_t           value = *p;
#else
#    error "TODO"
#endif
}
    const vsf_test_case_t __test_cases[] = {
        VSF_TEST_ADD(__test_pass, "test_pass hw_req=none", 0),
        VSF_TEST_ADD(__test_fail, "test_fail hw_req=none", 0),
        VSF_TEST_ADD(__test_wdt, "test_wdt hw_req=none", 0),
        VSF_TEST_ADD(__test_unalign, "test_invalid_address hw_req=none", 0),
    };
    
int vsf_test_main(void)
{
#if 1

    vsf_test_init(test, (vsf_test_case_t *)__test_cases, dimof(__test_cases));
#else
    static vsf_test_case_t __test_cases[10];
    vsf_test_init(test, __test_cases, dimof(__test_cases));
    vsf_test_add(test, __test_pass, "test_pass hw_req=none");
    vsf_test_add(test, __test_fail, "test_fail hw_req=none");
    vsf_test_add(test, __test_wdt, "test_wdt hw_req=none");
    vsf_test_add(test, __test_unalign, "test_invalid_address hw_req=none");
#endif

    vsf_test_run_tests(test);

    return 0;
}